import java.io.*;
import org.jfuse.*;

public class PassThru extends FuseHandler
{
	public static String base;

	public PassThru()
	{
		base = new File("test").getAbsolutePath();
	}

	public FuseStat getattr(String path) throws FuseResult
	{
		File f = new File(base + path);
		FuseStat res = new FuseStat();
		if (f.isDirectory()) {
			res.nlink = 2;
			res.mode = FuseStat.IFDIR + 0777;
			res.uid = 501;
			res.gid = 20;
		} else if (f.isFile()) {
			res.nlink = 2;
			res.mode = FuseStat.IFREG + 0666;
			res.size = f.length();
			res.uid = 501;
			res.gid = 20;
		} else if (!f.exists()) {
			throw new FuseResult(FuseResult.ENOENT);
		} else {
			throw new FuseResult(FuseResult.EPERM);
		}
		return res;
	}

	public String[] readdir(String path) throws FuseResult
	{
		File f = new File(base + path);
		String[] tmp = f.list();
		String[] res = new String[tmp.length + 2];
		res[0] = ".";
		res[1] = "..";
		for (int i=0; i<tmp.length; i++) res[i+2] = tmp[i];
		return res;
	}	
	
	public int read(String path, byte[] buffer, long offset) throws FuseResult
	{
		try {
			File f = new File(base + path);
			RandomAccessFile raf = new RandomAccessFile(f, "r");
			raf.seek(offset);
			int res = raf.read(buffer);
			raf.close();
			return res;
		} catch (IOException e) {
			e.printStackTrace();
			throw new FuseResult(FuseResult.EPERM);
		}
	}
		
	public int write(String path, byte[] buffer, long offset) throws FuseResult
	{
		try {
			File f = new File(base + path);
			RandomAccessFile raf = new RandomAccessFile(f, "rw");
			raf.seek(offset);
			raf.write(buffer);
			raf.close();
			return buffer.length;
		} catch (IOException e) {
			e.printStackTrace();
			throw new FuseResult(FuseResult.EPERM);
		}
	}
	
	public void mkdir(String path, int mode) throws FuseResult
	{
		File f = new File(base + path);
		if (!f.mkdir()) {
			System.err.println("cant mkdir " + f);
			throw new FuseResult(FuseResult.EPERM);
		}
	}
	
	public void unlink(String path) throws FuseResult
	{
		File f = new File(base + path);
		if (!f.delete()) throw new FuseResult(FuseResult.EPERM);
	}
	
	public void rmdir(String path) throws FuseResult
	{
		File f = new File(base + path);
		if (f.list().length > 0) throw new FuseResult(FuseResult.ENOTEMPTY);
		if (!f.delete()) throw new FuseResult(FuseResult.EPERM);
	}	
		
	public void rename(String from, String to) throws FuseResult
	{
		File f = new File(base + from);
		File g = new File(base + to);
		if (!f.renameTo(g)) throw new FuseResult(FuseResult.EPERM);
	}

	public void link(String from, String to) throws FuseResult
	{
		throw new FuseResult(FuseResult.ENOSYS);
	}
	
	public void create(String path, int mode) throws FuseResult
	{
		try {
			File f = new File(base + path);
			if (!f.createNewFile()) throw new FuseResult(FuseResult.EPERM);
		} catch (IOException e) {
			e.printStackTrace();
			throw new FuseResult(FuseResult.EPERM);
		}
	}		
	
	public void truncate(String path, long size) throws FuseResult
	{
		try {
			File f = new File(base + path);
			RandomAccessFile raf = new RandomAccessFile(f, "rw");
			raf.setLength(size);
			raf.close();
		} catch (IOException e) {
			e.printStackTrace();
			throw new FuseResult(FuseResult.EPERM);
		}
	}
	
	public FuseStatVFS statfs(String path) throws FuseResult
	{
		FuseStatVFS res = new FuseStatVFS();
		res.bsize = 4096;
		res.frsize = 4096;
		res.blocks = 1000;
		res.bfree = 1000;
		res.bavail = 1000;
		res.files = 1000;
		res.ffree = 1000;
		res.favail = 1000;
		res.fsid = 0;
		res.namemax = 4096;
		res.flag = FuseStatVFS.NOSUID;
		return res;
	}
	
	public static void main(String[] args) throws Exception
	{
		if (args.length != 2) {
			System.out.println("usage PassThru source-folder mount-point");
			return;
		}
		base = args[0]; // source
		String[] fuseArgs = new String[1+2+1];
		fuseArgs[0] = "-f";
		fuseArgs[1] = "-o";
		fuseArgs[2] = "allow_other,defer_permissions,noappledouble,noapplexattr,volname=PassThru,novncache";
		fuseArgs[2] = "allow_other,defer_permissions,auto_xattr,volname=PassThru,novncache,debug";
		fuseArgs[3] = args[1]; // mount point
		Fuse.main(fuseArgs, new PassThru());
	}
	
}

